/* 
Catching egg game v1.
SDL + Opengl with c++
Nguyen Hoai Dong
Email:hoaidongit5@gmail.com
*/

#include "Giacam.h"
#include "Egg.h"
#include <iostream>
#include <string>
#include <vector>
#include "SDL.h"
#include "SDL_image.h"
#include "SDL_ttf.h"
#include "SDL_opengl.h"
#include "SDL_mixer.h"

using namespace std;

#define PosT 50;//day tren

bool running = true;
bool isPlaying = true;//bat dau game
bool isMouseUpdated = false;//chuot
bool ischange = false;
bool isBackground = true;
bool key[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };//to hop phim dc nhan
int speed = 5;//toc do ban dau
int score = 0;//diem
int miss = 0;//miss egg
int shit = 0;//shit
Uint32 color;
Uint32 start;
Point2d posegg;//vi tri trung
SDL_Event event;
SDL_Surface * screen;
SDL_Surface *background;
char* scr = "Images/game.bmp";//anh nen load= SDL
SDL_Surface * imgGa;
SDL_Surface * imgVit;
SDL_Surface * imgNgan;
SDL_Surface * imgRo;
SDL_Surface * imgEgg;
SDL_Surface * imgShit;
Mix_Music *mus;//nhac

//list game

vector<Giacam*> listGiacam;
vector<Egg*> listEgg;
Gobj * ro;

SDL_Surface *loadImagePNG(string filename)//load anh SDL
{
	SDL_Surface *image = NULL;

	SDL_Surface *optimize = NULL;
	image = IMG_Load(filename.c_str());//load anh
	if (image != NULL)
	{
		optimize = SDL_DisplayFormat(image);
		SDL_FreeSurface(image);
	}
	if (image == NULL)
	{
		cout << "SDL_LoadBMP() Failed: " << SDL_GetError() << endl;//bao' loi
		exit(1);
	}
	if (optimize != NULL)
	{
		Uint32 colorkey = SDL_MapRGBA(optimize->format, 255, 255, 255, 0);
		SDL_SetColorKey(optimize, SDL_SRCCOLORKEY, colorkey);
		
	}
	return optimize;
};
GLuint loadTexture(const std::string &fileName) //load anh = SDL_opengl
{
	SDL_Surface *image = IMG_Load(fileName.c_str());

	SDL_DisplayFormatAlpha(image);

	unsigned object(0);

	glGenTextures(1, &object);

	glBindTexture(GL_TEXTURE_2D, object);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);

	//Free surface
	SDL_FreeSurface(image);

	return object;
};
void showMessage(int x, int y, char* nameMes, SDL_Surface* screen, int score, int sizefont)//ham ve text len screen
{
	SDL_Surface * message;
	SDL_Surface * Score;
	TTF_Font *font;
	SDL_Color textcolor = { 255, 0, 0 };
	TTF_Init();
	font = TTF_OpenFont("arial.ttf", sizefont);
	message = TTF_RenderText_Solid(font, nameMes, textcolor);
	SDL_Rect mespos;
	mespos.x = x;
	mespos.y = y;
	SDL_Rect scorepos;
	scorepos.x = mespos.x + message->clip_rect.w;//ghi score dau tien
	scorepos.y = mespos.y;
	char upscore[10];
	sprintf(upscore, "%d", score);
	Score = TTF_RenderText_Solid(font, upscore, textcolor);
	SDL_BlitSurface(message, NULL, screen, &mespos);
	SDL_BlitSurface(Score, NULL, screen, &scorepos);
	TTF_CloseFont(font);
	TTF_Quit();
}
void Update()//update game
{
	//update thong tin game
	Point2d eggpos;
	Egg *temp;
	bool egg = true;//egg = true, shit = flase
	for (unsigned int i = 0; i < listGiacam.size(); i++)//ve anh trung/shit
	{
		listGiacam[i]->Update();
		if (listGiacam[i]->isSinh())
		{
			eggpos = listGiacam[i]->getPos();
			if (rand() % 5 == 0)
			{
				egg = !egg;
			}
			if (egg)
			{
				//egg
				temp = new Egg(imgEgg, eggpos);
				temp->setEgg();
				listEgg.push_back(temp);
			}
			else
			{
				//shit
				temp = new Egg(imgShit, eggpos);
				temp->setShit();
				listEgg.push_back(temp);
			}
		}
	}
	//egg + shit
	for (unsigned int i = 0; i < listEgg.size(); i++)
	{
		//check roi xuong dat
		if (listEgg[i]->isDestroy())
		{
			if (listEgg[i]->isEgg())
			{
				miss++;
				if (miss == 3)//miss 3 egg -> gameover
				{
					isPlaying = false;
				}
			}
			listEgg.erase(listEgg.begin() + i);
		}
		//check lot vao ro
		if (ro->checkCollision(listEgg[i]->getBox(), ro->getBox()))
		{
			if (listEgg[i]->isEgg())
			{
				ischange = true;
				score += 2;
			}
			else
			{
				shit++;
				if (shit == 3)//3 shit -> gameover
				{
					isPlaying = false;
				}
			}
			listEgg.erase(listEgg.begin() + i);
		}
		if (score != 0 && score % 20 == 0 && ischange)//ham gia tang do roi trung
		{
			speed += 2;
			ischange = false;
		}
		listEgg[i]->Update(speed);
	}

	if (isMouseUpdated)
	{
		Point2d mouse;
		mouse.x = event.motion.x - imgRo->w / 2;
		mouse.y = LINE - imgRo->h;//co dinh cai ro theo y
		ro->SetPosition(mouse);
		isMouseUpdated = false;
	}
	ro->Update();//move ro
	if (key[0])
		ro->Move(-22, 0);
	if (key[1])
		ro->Move(22, 0);
}
void Draw(SDL_Surface* screen)//ve game
{
	//ve lan dau vao game
	//set anh nen
	SDL_BlitSurface(background, NULL, screen, &screen->clip_rect);
	for (unsigned int i = 0; i < listGiacam.size(); i++)
	{
		listGiacam[i]->Draw(screen);
	}
	//ve egg/shit
	for (unsigned int i = 0; i < listEgg.size(); i++)
	{
		listEgg[i]->Draw(screen);
	}
	//ve ro
	ro->Draw(screen);
	//ve message
	char* nameScore = "Score:  ";
	showMessage(5, 5, nameScore, screen, score, 18);
	char* nameMiss = "Miss: ";
	showMessage(118, 5, nameMiss, screen, miss, 18);
	char* nameShit = "Shit: ";
	showMessage(225, 5, nameShit, screen, shit, 18);
	char* level = "Speed: ";
	showMessage(313, 5, level, screen, speed, 18);
	char* exit1 = "Exit press E ";
	showMessage(300, 610, exit1, screen, NULL, 18);
	char* help = "Help press H                                                                     ";
	showMessage(5, 610, help, screen, NULL, 18);
}

void GameOver()//thong bao ket thuc game
{
	color = SDL_MapRGB(screen->format, 0, 255, 0);
	char* gameOver = "Game Over...!";
	showMessage(90,420, gameOver, screen, NULL, 50);
	char* games = "                 Press S to try again...!";
	showMessage(100, 480, games, screen, NULL, 20);
}
void mouseFunc()//event chuot
{
	isMouseUpdated = true;
}
void Xoagame()//xoa het tat ca
{
	SDL_FreeSurface(screen);
	SDL_FreeSurface(imgGa);
	SDL_FreeSurface(imgVit);
	SDL_FreeSurface(imgNgan);
	SDL_FreeSurface(imgRo);
	SDL_FreeSurface(imgEgg);
	SDL_FreeSurface(imgShit);
	SDL_FreeSurface(background);
	while (!listGiacam.empty())
	{
		Giacam * giacam = listGiacam[listGiacam.size() - 1];
		listGiacam.pop_back();
		delete giacam;
	}
	while (!listEgg.empty())
	{
		Egg * egg = listEgg[listEgg.size() - 1];
		listEgg.pop_back();
		delete egg;
	}
	delete ro;
}

void loop()// main game
{
	Point2d pos;
	pos.x = PosT;//vi tri con gia cam add
	pos.y = 50;
	const int FPS = 30;
	while (running)
	{
		start = SDL_GetTicks();
		while (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
			case SDL_MOUSEMOTION:
				mouseFunc(); break;
			case SDL_QUIT:
				running = false; break;
			case SDL_KEYDOWN:
				switch (event.key.keysym.sym)
				{
				case SDLK_LEFT:
					key[0] = 1; break;
				case SDLK_RIGHT:
					key[1] = 1; break;
				case SDLK_g:
					key[2] = 1; break;
				case SDLK_v:
					key[3] = 1; break;
				case SDLK_n:
					key[4] = 1; break;
				case SDLK_e:
					key[5] = 1; break;
				case SDLK_h:
					key[6] = 1; break;
				case SDLK_s:
					key[7] = 1; break;
				}
				break;
			case SDL_KEYUP:
				switch (event.key.keysym.sym)
				{
				case SDLK_LEFT:
					key[0] = 0; break;
				case SDLK_RIGHT:
					key[1] = 0; break;
				case SDLK_g:
				{
							   listGiacam.push_back(new Giacam(imgGa, pos));
							   key[2] = 0;
							   break;
				}
				case SDLK_v:
				{
							   listGiacam.push_back(new Giacam(imgVit, pos));
							   key[3] = 0;
							   break;
				}
				case SDLK_n:
				{
							   listGiacam.push_back(new Giacam(imgNgan, pos));
							   key[4] = 0;
							   break;
				}
				case SDLK_e:
				{
							   exit(0);
							   break;
				}
				case SDLK_h:
				{
							   char* help10 = "Press V to add duck.                        ";
							   char* help9 = "Press N to add goose.                        ";
							   char* help8 = "Press G to add chicken.                         ";
							   char* help7 = "Press S to start game!                          ";
							   char* help6 = "   will beincreased, restart the game to play.            ";
							   char* help5 = " or catch 3 shits you will lose.                           ";
							   char* help4 = " to control the basket to catch the eggs of birds.     ";
							   char* help3 = "When the level reaches score of the game level     ";
							   char* help2 = " Birds lay egg can also lay shits, miss 3 egg                 ";
							   char* help1 = " You can use the mouse or keys to left to right          ";
							   char* help = " This is the game catching eggs.                                     ";
							   showMessage(70, 150, help, screen, NULL, 18);
							   showMessage(15, 170, help1, screen, NULL, 18);
							   showMessage(15, 190, help4, screen, NULL, 18);
							   showMessage(19, 210, help2, screen, NULL, 18);
							   showMessage(85, 230, help5, screen, NULL, 18);
							   showMessage(15, 250, help3, screen, NULL, 18);
							   showMessage(25, 270, help6, screen, NULL, 18);
							   showMessage(120, 290, help8, screen, NULL, 18);
							   showMessage(124, 310, help9, screen, NULL, 18);
							   showMessage(127, 330, help10, screen, NULL, 18);
							   showMessage(120, 350, help7, screen, NULL, 18);
							   isPlaying = false;
							   key[6] = 0;
							   break;
				}
				case SDLK_s:
				{
							   speed = 5;
							   score = 0;
							   miss = 0;
							   shit = 0;
							   running = true;
							   isPlaying = true;
							   key[7] = 0;
							   break;
				}
				}
				break;
			default:
				break;
			}
		}
		if (isPlaying)
		{
			Update();
			Draw(screen);
		}
		else
		{
			GameOver();
		}
		SDL_Flip(screen);
		if (1000 / FPS > (SDL_GetTicks() - start))
		{
			SDL_Delay(1000 / FPS - (SDL_GetTicks() - start));
		}
	}
	Xoagame();	
}
int main(int __argc, char** argv)
{
	//mo cua so game
	SDL_Init(SDL_INIT_EVERYTHING);
	screen = SDL_SetVideoMode(400, 630, 32, SDL_SWSURFACE);
	color = SDL_MapRGB(screen->format, 255, 255, 255);
	/*	glMatrixMode(GL_PROJECTION);                 //load = SDL_opengl nhung fail
	glLoadIdentity();
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	unsigned int back_texture = 0;
	back_texture = loadTexture("Images/game.bmp");
	glClear(GL_COLOR_BUFFER_BIT);
	glPushMatrix();
	glOrtho(0, 400, 630, 0, -1, 1); 
	glColor4ub(255, 255, 255, 255); 
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, back_texture);
    //set anh
	glBegin(GL_QUADS);
	glTexCoord2d(0, 0); glVertex2f(0, 0);
	glTexCoord2d(1, 0); glVertex2f(400, 0);
	glTexCoord2d(1, 1); glVertex2f(400, 630);
	glTexCoord2d(0, 1); glVertex2f(0, 630);
	glEnd();*/
	background = IMG_Load(scr);// load anh SDL
	imgGa = loadImagePNG("Images/ga.bmp");
	imgVit = loadImagePNG("Images/vit.bmp");
	imgNgan = loadImagePNG("Images/ngan.bmp");
	imgRo = loadImagePNG("Images/ro.bmp");
	imgEgg = loadImagePNG("Images/egg.bmp");
	imgShit = loadImagePNG("Images/shit.bmp");
	SDL_WM_SetCaption("Catching Eggs.                                             Make by Hoai Dong", NULL);
	//nhac game
	//Mix_OpenAudio(22050, AUDIO_S16SYS, 2, 640);
	//mus = Mix_LoadMUS("Images/nhacnen.mid");
	//Mix_PlayMusic(mus, 1); //tat nhac de load game nhanh
	
	//khoi dong game o day
	//set gia cam
	Point2d pos;
	pos.x = PosT;
	pos.y = 50;
	//set cai ro
	Point2d roPos;
	roPos.x = 100;
	roPos.y = LINE - imgRo->h;
	ro = new Gobj(imgRo, roPos);
	//add con vit
	listGiacam.push_back(new Giacam(imgGa, pos));
	loop();
	SDL_Quit();
	//system("pause");
	return 0;
}